package org.zoomdy.gdbx;

import java.io.IOException;
import java.util.logging.Level;

public class JoinNode extends Node
{
    final static String version = "1.0.0";
    
    boolean targetRunning;
    
    public JoinNode(String id)
    {
        super(id);
        
        this.targetRunning = false;
    }
    
    String getVersion()
    {
        return JoinNode.version;
    }
    
    public void run()
    {
        assert this.serverPort > 0;
        assert this.clientHost != null;
        assert this.clientPort > 0;
        
        int recvChannels = this.CHANNEL_ANY;
        
        try
        {
            while(this.nodeState != Node.NodeState.QUIT)
            {
                this.logger.entering("org.zoomdy.gdbx.JoinNode", "run");
                
                // 只有在目标机处于运行状态时，才能转发调试输出数据，
                // 当目标机处于停机状态时，转发调试输出数据将扰乱GDB请求。
                if(this.targetRunning)
                {
                    recvChannels |= this.CHANNEL_EXTENDER;
                }
                else
                {
                    recvChannels &= ~this.CHANNEL_EXTENDER;
                }
                
                Packet packet = this.recvPacket(recvChannels);
                if(packet == null)
                {
                    continue;
                }
                
                if((packet.channels & this.CHANNEL_SERVER) == this.CHANNEL_SERVER)
                {
                    if(packet.isRunPacket())
                    {
                        this.targetRunning = true;
                    }
                    
                    packet.channels = this.CHANNEL_CLIENT;
                    this.sendPacket(packet);
                }
                else if((packet.channels & this.CHANNEL_CLIENT) == this.CHANNEL_CLIENT)
                {
                    if(packet.isStopPacket())
                    {
                        this.targetRunning = false;
                    }
                    
                    packet.channels = this.CHANNEL_SERVER;
                    this.sendPacket(packet);
                }
                else if((packet.channels & this.CHANNEL_EXTENDER) == this.CHANNEL_EXTENDER)
                {
                    if(packet.isPrint())
                    {
                        Packet outputPacket = packet.toGdbOutputPacket();
                        if(outputPacket != null)
                        {
                            outputPacket.channels = this.CHANNEL_SERVER;
                            this.sendPacket(outputPacket);
                            if(this.noAckMode == false)
                            {
                                packet = this.recvPacket(this.CHANNEL_SERVER); // get Acknowledgment
                            }
                        }
                    }
                    else
                    {
                        this.logger.warning("Can not print this packet!");
                    }
                }
                
                this.logger.exiting("org.zoomdy.gdbx.JionNode", "run");
            }
        }
        catch(IOException e) 
        {
            e.printStackTrace();
        }
    }
    
    public String[] parseArgs(String[] args)
    {
        String[] remainArgs = super.parseArgs(args);
        
        return remainArgs;
    }
    
    public String usage()
    {
        String s = super.usage();
        s += "JoinNode.\n";
        
        return s;
    }

    public static void main(String[] args) {
        JoinNode node = new JoinNode("join-node");

        String[] remainArgs = node.parseArgs(args);
        if(remainArgs.length > 0 && remainArgs[0] != null)
        {
            for(int i = 0; i < remainArgs.length; i++)
            {
                if(remainArgs[i] == null)
                {
                    break;
                }
                
                System.out.println("unrecognized option: " + remainArgs[i]);
            }
            System.out.print(node.usage());
            return;
        }
        
        node.setLoggerLevel(Level.WARNING);
        node.run();
    }
}
